import pymysql.connections
import pymysql.cursors
import pymysql

# import scan.entity.Target

from CoTec.utility.string.string_go import genUUID
from CoTec.core.log.log_go import LogGo

# import CoTec.core.config.global_var
from CoTec.core.exception.exception_go import *

from CoTec.core.output.output_go import OutGo
# from CoTec.core.config.global_var import Variables

import threading
import multiprocessing

class MysqlGoQueueVer(object):

    config = None

    def __new__(cls, conf):
        if not hasattr(cls, 'instance'):
            cls.instance = super(MysqlGoQueueVer, cls).__new__(cls)
            cls.config = conf
            cls.instance.init(conf.database_address, conf.database_name, conf.database_account, conf.database_pass)
        return cls.instance

    def init(self, host, database, user, password):
        try:
            self.connection = pymysql.connect(host=host, user=user, password=password, db=database, charset='utf8mb4')
            manager = multiprocessing.Manager()

            self.queue = manager.Queue(1)
            self.queue = manager.Queue(1)
            self.queue = manager.Queue(1)
            self.queue = manager.Queue(1)
            self.queue = manager.Queue(1)

            self.mutex = threading.Lock()
            return True
        except Exception as e:
            LogGo.warning(repr(e))
            raise DataBaseConnectFailedException

    # def __init__(self, config=None):
    #     if config is not None:
    #         self.config = config
    #
    #     conf = self.config
    #
    #     try:
    #         self.connection = pymysql.connect(host=conf.database_address, user=conf.database_account, password=conf.database_pass, db=conf.database_name, charset='utf8mb4')
    #         self.mutex = threading.Lock()
    #     except Exception as e:
    #         LogGo.warning('at init: ' + repr(e))
    #         raise DataBaseConnectFailedException

    @staticmethod
    def init(conf):
        MysqlGoQueueVer.config = conf

    def save(self,sql,parameter):
        if self.mutex.acquire():
            if self.config.display_sql:
                OutGo.pr(sql)

            try:
                with self.connection.cursor() as cursor:
                    cursor.execute(sql, parameter)
                self.connection.commit()
            except Exception as e:
                import traceback
                msg = traceback.format_exc()
                LogGo.warning('at save: ' + msg)
                raise DatabaseOperationException
            finally:
                self.connection.close()
                self.mutex.release()

    def execute_sql_with_par(self,sql,parameter):
        if self.mutex.acquire():
            if self.config.display_sql:
                OutGo.pr(sql)

            try:
                with self.connection.cursor() as cursor:
                    cursor.execute(sql, parameter)

                self.connection.commit()

            except Exception as e:
                import traceback
                msg = traceback.format_exc()
                LogGo.warning('at execute sql with par: ' + msg)
                raise DatabaseOperationException
            finally:
                self.connection.close()
                self.mutex.release()

    def update(self,sql):
        if self.mutex.acquire():
            if self.config.display_sql:
                OutGo.pr(sql)

            sta = False

            try:
                with self.connection.cursor() as cursor:
                    sta = cursor.execute(sql)

                self.connection.commit()

                return sta

            except Exception as e:
                import traceback
                msg = traceback.format_exc()
                LogGo.warning('at update: ' + msg)
                raise DatabaseOperationException
            finally:
                self.connection.close()
                self.mutex.release()

    def load_no_dic(self,sql,**pars):
        if self.mutex.acquire():
            if self.config.display_sql:
                OutGo.pr(sql)

            try:
                with self.connection.cursor(cursor=pymysql.cursors.DictCursor) as cursor:

                    adding = ""

                    for key in pars:
                        if key == 'val':
                            adding = pars[key]
                            break

                    if adding == "":
                        cursor.execute(sql)
                    else:
                        cursor.execute(sql, pars[key])

                    result = cursor.fetchall()

                self.connection.commit()

                return result

            except Exception as e:
                import traceback
                msg = traceback.format_exc()
                LogGo.warning('at load no dic: ' + msg)
                raise DatabaseOperationException
            finally:
                self.connection.close()
                self.mutex.release()

    def load(self,sql,**pars):
        if self.mutex.acquire(100):
            if self.config.display_sql:
                OutGo.pr(sql)

            try:
                with self.connection.cursor(cursor=pymysql.cursors.DictCursor) as cursor:

                    adding = ""

                    for key in pars:
                        if key == 'val':
                            adding = pars[key]
                            break

                    if adding == "":
                        cursor.execute(sql)
                    else:
                        cursor.execute(sql, pars[key])

                    result = cursor.fetchall()

                self.connection.commit()

                return result
            except Exception as e:
                import traceback
                msg = traceback.format_exc()
                LogGo.warning('at load: ' + msg)
                raise e
            finally:
                self.connection.close()
                self.mutex.release()



